﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Declarations;
using Declarations.Events;
using Declarations.Media;
using Declarations.Players;
using Implementation;
using iNet.Media.Audio;
using iNet.Tasks;

namespace iNet.Media.Video
{
	public unsafe class VlcVideo : MediaBase, IVideo, INotifyPropertyChanged
	{
		#region 靜態欄位
		static readonly IMediaPlayerFactory _MediaPlayerFactory = new MediaPlayerFactory();
		#endregion
		#region 欄位
		volatile bool _CanSeek;
		long? _Duration;
		volatile EventHandler<DataEventArgs<long?>> _DurationChangedHandlers;
		readonly object _EventSyncRoot = new object();
		volatile bool _HasAudio;
		volatile bool _HasVideo;
		volatile bool _IsDisposed;
		volatile bool _IsMuted;
		volatile bool _IsVolumeSync;
		Declarations.Media.IMedia _Media;
		PlayableMediaState _MediaState = PlayableMediaState.Stopped;
		volatile EventHandler<ValueChangedEventArgs<PlayableMediaState>> _MediaStateChangedHandlers;
		volatile EventHandler _PlayablePositionChangedHandlers;
		long? _PlayablePositionEnd;
		long? _PlayablePositionStart;
		long? _Position;
		volatile EventHandler<DataEventArgs<long?>> _PositionChangedHandlers;
		volatile IMediaFormat _RawAudioFormat;
		IMediaFormat _RawContainerFormat;
		volatile IMediaFormat _RawVideoFormat;
		IntPtr _VideoOutputWindowHandle;
		volatile int _VideoPixelHeight;
		volatile int _VideoPixelWidth;
		IVideoPlayer _VideoPlayer;
		double _Volume = 0.5;
		#endregion
		#region 建構子
		public VlcVideo(MediaStorage mediaStorage, bool isReadOnly, IMetadata metadata, IMediaFormat containerFormat)
			: base(mediaStorage, isReadOnly, metadata)
		{
			//載入媒體
			if (!this.OpenMedia(false))
				throw new ArgumentException();

			//取得影音資訊
			if (_Media is IMediaFromFile)
				this.ParseMedia(false);

			//取得初始狀態
			this.ChangeMediaState(_Media.State);

			//儲存格式
			_RawContainerFormat = containerFormat;
		}
		private VlcVideo(VlcVideo video, bool isReadOnly)
			: base(video.MediaStorage, isReadOnly, video.Metadata)
		{
			//複製影片資訊
			_HasAudio = video._HasAudio;
			_HasVideo = video._HasVideo;
			_RawAudioFormat = video._RawAudioFormat;
			_RawVideoFormat = video._RawVideoFormat;
			_RawContainerFormat = video._RawContainerFormat;
			_CanSeek = video._CanSeek;
			_Duration = video._Duration;
			if (_Duration != null)
			{
				_Position = 0;
				_PlayablePositionStart = 0;
				_PlayablePositionEnd = _Duration;
			}
			_Volume = video._Volume;
			_VideoPixelWidth = video._VideoPixelWidth;
			_VideoPixelHeight = video._VideoPixelHeight;
		}
		#endregion
		#region Balance
		public double Balance
		{
			get
			{
				return 0;
			}
			set
			{ }
		}
		#endregion
		#region CanPause
		public bool CanPause
		{
			get
			{
				lock (this)
				{
					if (_VideoPlayer != null)
						return _VideoPlayer.CanPause;
					return false;
				}
			}
		}
		#endregion
		#region CanSeek
		public bool CanSeek
		{
			get
			{
				return _CanSeek;
			}
		}
		#endregion
		#region ChangeMediaState
		void ChangeMediaState(MediaState vlcMediaState)
		{
			//轉換狀態
			PlayableMediaState mediaState;
			switch (vlcMediaState)
			{
				case Declarations.MediaState.Opening:
					return;
				case Declarations.MediaState.Buffering:
				case Declarations.MediaState.Paused:
					mediaState = PlayableMediaState.Paused;
					break;
				case Declarations.MediaState.Playing:
					mediaState = PlayableMediaState.Playing;
					break;
				case Declarations.MediaState.NothingSpecial:
				case Declarations.MediaState.Ended:
				case Declarations.MediaState.Stopped:
					mediaState = PlayableMediaState.Stopped;
					break;
				default:
					mediaState = PlayableMediaState.Error;
					break;
			}

			//變更狀態
			this.ChangeMediaState(mediaState);
		}
		void ChangeMediaState(PlayableMediaState mediaState)
		{
			//變更狀態
			PlayableMediaState oldMediaState;
			lock (this)
			{
				//變更狀態
				if (_MediaState == mediaState)
					return;
				oldMediaState = _MediaState;
				_MediaState = mediaState;

				//釋放播放器
				if (mediaState == PlayableMediaState.Stopped || mediaState == PlayableMediaState.Error)
				{
					if (_Media != null)
					{
						_Media.Dispose();
						_Media = null;
					}
					/*
					IVideoPlayer videoPlayer = _VideoPlayer;
					//IMemoryRendererEx videoRenderer = _VideoFrameRenderer;
					//IMediaPlayerFactory factory = _MediaPlayerFactory;
					ThreadPool.QueueUserWorkItem((state) =>
					{
						Thread.Sleep(3000);
						this.FreeVideoPlayer(videoPlayer, null);
						//if (factory != null)
							//factory.Dispose();
					});
					_VideoPlayer = null;
					*/
					//_MediaPlayerFactory = new MediaPlayerFactory();
					//_VideoFrameRenderer = null;
					if (_VideoPlayer != null)
						_VideoPlayer.WindowHandle = IntPtr.Zero;
					if (_Position != null)
						this.OnVideoPlayerPositionChanged(0);
				}
			}

			//引發事件
			lock (_EventSyncRoot)
			{
				if (_MediaStateChangedHandlers != null)
					_MediaStateChangedHandlers(this, new ValueChangedEventArgs<PlayableMediaState>(oldMediaState, mediaState));
			}
		}
		#endregion
		#region Clone
		public override MediaBase Clone()
		{
			lock (this)
			{
				if (_IsDisposed)
					throw new ObjectDisposedException("");
				return new VlcVideo(this, false);
			}
		}
		#endregion
		#region Dispose
		protected override void Dispose(bool disposing)
		{
			//釋放其他資源
			lock (this)
			{
				if (!_IsDisposed)
				{
					//停止播放
					if (_VideoPlayer != null)
					{
						_VideoPlayer.Stop();
						_VideoPlayer.Dispose();
						_VideoPlayer = null;
					}
					if (_Media != null)
					{
						_Media.Dispose();
						_Media = null;
					}
					this.ChangeMediaState(PlayableMediaState.Stopped);

					//變更狀態
					_IsDisposed = true;
				}
			}

			//呼叫基底
			base.Dispose(disposing);
		}
		#endregion
		#region Duration
		public long? Duration
		{
			get 
			{
				return _Duration;
			}
		}
		#endregion
		#region DurationChanged
		public event EventHandler<DataEventArgs<long?>> DurationChanged
		{
			add
			{
				lock (_EventSyncRoot)
				{
					_DurationChangedHandlers += value;
				}
			}
			remove
			{
				lock (_EventSyncRoot)
				{
					_DurationChangedHandlers -= value;
				}
			}
		}
		#endregion
		#region FreeVideoPlayer
		void FreeVideoPlayer(IVideoPlayer videoPlayer, IMemoryRendererEx videoRenderer)
		{
			if (videoPlayer != null)
				videoPlayer.Dispose();
			if (videoRenderer != null)
				videoRenderer.Dispose();
		}
		#endregion
		#region GetAsReadOnly
		public override IMedia GetAsReadOnly()
		{
			if (this.IsReadOnly)
				return this;
			lock (this)
			{
				if (_IsDisposed)
					throw new ObjectDisposedException("");
				return new VlcVideo(this, true);
			}
		}
		#endregion
		#region GetCurrentVideoFrame
		/*
		public bool GetCurrentVideoFrame(WriteableBitmap buffer)
		{
			//確認參數
			if (buffer == null)
				throw new ArgumentNullException("buffer");

			//複製畫面資料
			lock (_VideoFrameBufferLock)
			{
				//確認狀態
				if (_VideoFrameBuffer == IntPtr.Zero)
					return false;

				//取得畫面資訊
				int stride = (_VideoPixelWidth * 4);
				int dataSize = (stride * _VideoPixelHeight);

				//修正色彩
				if (!m_IsVideoFrameColorCorrected)
				{
					m_IsVideoFrameColorCorrected = true;
					int pixelCount = (_VideoPixelWidth * _VideoPixelHeight);
					byte* pixelPtr = (byte*)_VideoFrameBuffer;
					for (int i = pixelCount; i > 0; --i, pixelPtr += 4)
					{
						byte r = pixelPtr[0];
						pixelPtr[0] = pixelPtr[2];
						pixelPtr[2] = r;
					}
				}

				//複製畫面資料
				try
				{
					if (buffer.PixelWidth == _VideoPixelWidth
						&& buffer.PixelHeight == _VideoPixelHeight
						&& buffer.Format == this.VideoPixelFormat)
					{
						buffer.Lock();
						buffer.AddDirtyRect(new Int32Rect(0, 0, _VideoPixelWidth, _VideoPixelHeight));
						iNet.Win32.Kernel32.CopyMemory(buffer.BackBuffer, _VideoFrameBuffer, dataSize);
						buffer.Unlock();
					}
					else
					{
						//建立原始點陣圖
						BitmapSource originalBitmap = BitmapSource.Create(_VideoPixelWidth, _VideoPixelHeight, 96, 96, PixelFormats.Bgra32, null, _VideoFrameBuffer, dataSize, stride);

						//調整大小
						if (buffer.PixelWidth != _VideoPixelWidth || buffer.PixelHeight != _VideoPixelHeight)
						{
							double scaleX = (buffer.PixelWidth / (double)_VideoPixelWidth);
							double scaleY = (buffer.PixelHeight / (double)_VideoPixelHeight);
							originalBitmap = new TransformedBitmap(originalBitmap, new ScaleTransform(scaleX, scaleY));
						}

						//調整格式
						if (buffer.Format != PixelFormats.Bgra32 && buffer.Format != PixelFormats.Bgr32)
							originalBitmap = new FormatConvertedBitmap(originalBitmap, buffer.Format, buffer.Palette, 0.5);

						//複製至目標點陣圖
						stride = (buffer.Format.BitsPerPixel * buffer.PixelWidth);
						int linePadding = (8 - (stride % 8));
						stride /= 8;
						if (linePadding < 8)
							++stride;
						dataSize = (stride * buffer.PixelHeight);
						IntPtr pixelBuffer = Marshal.AllocHGlobal(dataSize);
						try
						{
							Int32Rect rect = new Int32Rect(0, 0, buffer.PixelWidth, buffer.PixelHeight);
							originalBitmap.CopyPixels(rect, pixelBuffer, dataSize, stride);

							buffer.WritePixels(rect, pixelBuffer, dataSize, stride);
						}
						finally
						{
							Marshal.FreeHGlobal(pixelBuffer);
						}
					}
				}
				catch
				{
					return false;
				}

				//複製完成
				return true;
			}
		}
		*/
		#endregion
		#region GetMediaFormat
		static IMediaFormat GetMediaFormat(string codec)
		{
			switch (codec)
			{
				case "cook":
					return AudioFormats.RealAudio;
				case "DIV3":
				case "DIV4":
				case "DIV5":
					return VideoFormats.DivXMpeg4;
				case "DIVX":
					return VideoFormats.DivX;
				case "h264":
					return VideoFormats.H264;
				case "MJPG":
					return VideoFormats.MotionJpeg;
				case "mp4a":
					return AudioFormats.Mpeg4Audio;
				case "RV20":
				case "RV30":
				case "RV40":
					return VideoFormats.RealVideo;
				case "s16l":
					return AudioFormats.Pcm16;
				case "u20 ":
					return AudioFormats.Pcm20;
				case "u24 ":
					return AudioFormats.Pcm24;
				case "u8  ":
					return AudioFormats.Pcm8;
				case "VC-1":
					return VideoFormats.Vc1;
				case "WMA2":
					return AudioFormats.Wma;
				case "WMV2":
				case "WMV3":
				case "WMVA":
					return VideoFormats.Wmv;
				case "WVC1":
					return VideoFormats.Wvc1;
				default:
					return null;
			}
		}
		#endregion
		#region HasAudio
		public bool HasAudio
		{
			get
			{
				return _HasAudio;
			}
		}
		#endregion
		#region HasError
		public bool HasError
		{
			get
			{
				return (_MediaState == PlayableMediaState.Error);
			}
		}
		#endregion
		#region HasVideo
		public bool HasVideo
		{
			get 
			{
				return _HasVideo;
			}
		}
		#endregion
		#region IsMuted
		public bool IsMuted
		{
			get
			{
				return _IsMuted;
			}
			set
			{
				lock (this)
				{
					if (_IsDisposed)
						throw new ObjectDisposedException("");
					_IsMuted = value;
					if (_VideoPlayer != null)
						_VideoPlayer.Mute = value;
				}
			}
		}
		#endregion
		#region MediaState
		public PlayableMediaState MediaState
		{
			get
			{
				return _MediaState;
			}
		}
		#endregion
		#region MediaStateChanged
		public event EventHandler<ValueChangedEventArgs<PlayableMediaState>> MediaStateChanged
		{
			add
			{
				lock (_EventSyncRoot)
				{
					_MediaStateChangedHandlers += value;
				}
			}
			remove
			{
				lock (_EventSyncRoot)
				{
					_MediaStateChangedHandlers -= value;
				}
			}
		}
		#endregion
		#region OnMediaStateChanged
		void OnMediaStateChanged(object sender, MediaStateChange e)
		{
			this.ChangeMediaState(e.NewState);
		}
		#endregion
		#region OnPropertyChanged
		void OnPropertyChanged(string propertyName)
		{
			PropertyChangedEventHandler handlers = this.PropertyChanged;
			if (handlers != null)
				handlers(this, new PropertyChangedEventArgs(propertyName));
		}
		#endregion
		#region OnVideoPlayerLengthChanged
		void OnVideoPlayerLengthChanged(object sender, MediaPlayerLengthChanged e)
		{
			bool isPositionChanged = false;
			long? newPosition = null;
			lock (this)
			{
				if (_VideoPlayer != sender)
					return;
				if (_Duration == e.NewLength)
					return;
				if (_Duration == null)
				{
					isPositionChanged = true;
					this.ParseMedia(true);
					_Position = 0;
					newPosition = 0;
				}
				_Duration = e.NewLength;
			}
			lock (_EventSyncRoot)
			{
				if (_DurationChangedHandlers != null)
					_DurationChangedHandlers(this, new DataEventArgs<long?>(e.NewLength));
				if (isPositionChanged && _PositionChangedHandlers != null)
					_PositionChangedHandlers(this, new DataEventArgs<long?>(newPosition));
			}
		}
		#endregion
		#region OnVideoPlayerPositionChanged
		void OnVideoPlayerPositionChanged(object sender, MediaPlayerPositionChanged e)
		{
			long position;
			lock (this)
			{
				if (_VideoPlayer != sender)
					return;
				if (!_IsVolumeSync)
				{
					_VideoPlayer.Mute = _IsMuted;
					_VideoPlayer.Volume = (int)(_Volume * 100 + 0.5);
					_IsVolumeSync = true;
				}
				switch (_MediaState)
				{
					case PlayableMediaState.Playing:
					case PlayableMediaState.Paused:
						if (_Duration == null)
							return;
						position = (long)(_Duration * e.NewPosition);
						break;
					default:
						return;
				}
			}
			this.OnVideoPlayerPositionChanged(position);
		}
		void OnVideoPlayerPositionChanged(long position)
		{
			lock (_EventSyncRoot)
			{
				_Position = position;
				if (_PositionChangedHandlers != null)
					_PositionChangedHandlers(this, new DataEventArgs<long?>(position));
			}
		}
		#endregion
		#region OpenMedia
		bool OpenMedia(bool parseAsync)
		{
			//確認狀態
			if (_Media != null)
				return true;

			//取得檔案路徑
			string filePath = null;
			bool isLocalFile = false;
			switch (this.MediaStorage.StorageType)
			{
				case MediaStorageType.File:
					filePath = this.MediaStorage.FileName;
					isLocalFile = true;
					break;
				case MediaStorageType.Uri:
					filePath = this.MediaStorage.Uri.AbsoluteUri;
					break;
				case MediaStorageType.WebRequest:
					filePath = this.MediaStorage.WebRequest.RequestUri.AbsoluteUri;
					break;
				default:
					return false;
			}

			//開啟影片
			try
			{
				//開啟影片
				if (isLocalFile)
					_Media = _MediaPlayerFactory.CreateMedia<IMediaFromFile>(filePath);
				else
					_Media = _MediaPlayerFactory.CreateMedia<Declarations.Media.IMedia>(filePath);
				_Media.Parse(parseAsync);

				//事件連結
				_Media.Events.StateChanged += this.OnMediaStateChanged;
				return true;
			}
			catch
			{
				this.ChangeMediaState(PlayableMediaState.Error);
				return false;
			}
		}
		#endregion
		#region ParseMedia
		bool ParseMedia(bool raiseEvents)
		{
			//確認狀態
			if (_Media == null && !this.OpenMedia(false))
				return false;

			//取得影音資訊
			try
			{
				MediaTrack[] tracks = _Media.TracksInfoEx;
				if (tracks != null)
				{
					for (int i = tracks.Length - 1; i >= 0; --i)
					{
						MediaTrack track = tracks[i];
						if (track is AudioTrack)
						{
							AudioTrack audioTrack = (track as AudioTrack);
							_RawAudioFormat = GetMediaFormat(audioTrack.Codec);
							if (raiseEvents)
								this.OnPropertyChanged("RawAudioFormat");
							if (!_HasAudio)
							{
								_HasAudio = true;
								if (raiseEvents)
									this.OnPropertyChanged("HasAudio");
							}
						}
						else if (track is VideoTrack)
						{
							VideoTrack videoTrack = (track as VideoTrack);
							_RawVideoFormat = GetMediaFormat(videoTrack.Codec);
							_VideoPixelWidth = (int)videoTrack.Width;
							_VideoPixelHeight = (int)videoTrack.Height;
							if (raiseEvents)
							{
								this.OnPropertyChanged("RawVideoFormat");
								this.OnPropertyChanged("VideoPixelWidth");
								this.OnPropertyChanged("VideoPixelHeight");
							}
							if (!_HasVideo)
							{
								_HasVideo = true;
								if (raiseEvents)
									this.OnPropertyChanged("HasVideo");
							}
						}
					}
				}
			}
			catch
			{
				return false;
			}

			//取得時間長度
			try
			{
				if (_Media is IMediaFromFile)
				{
					_CanSeek = true;
					_Duration = (_Media as IMediaFromFile).Duration;
					_Position = 0;
					_PlayablePositionStart = 0;
					_PlayablePositionEnd = _Duration;
					if (raiseEvents)
					{
						this.OnPropertyChanged("CanSeek");
					}
				}
			}
			catch
			{
				return false;
			}

			//完成
			return true;
		}
		#endregion
		#region Pause
		public void Pause()
		{
			lock (this)
			{
				//確認狀態
				if (_IsDisposed)
					throw new ObjectDisposedException("VlcVideo");
				if (_MediaState != PlayableMediaState.Playing)
					return;

				//暫停
				if (_VideoPlayer != null && _VideoPlayer.CanPause)
					_VideoPlayer.Pause();
				this.ChangeMediaState(PlayableMediaState.Paused);
			}
		}
		#endregion
		#region Play
		public void Play()
		{
			//播放
			lock (this)
			{
				//確認狀態
				if (_IsDisposed)
					throw new ObjectDisposedException("VlcVideo");
				if (_MediaState == PlayableMediaState.Error || _MediaState == PlayableMediaState.Playing)
					return;

				//開啟影片
				if (!this.OpenMedia(true))
					return;

				//建立播放器
				if (_VideoPlayer == null)
				{
					_VideoPlayer = _MediaPlayerFactory.CreatePlayer<IVideoPlayer>();
					_VideoPlayer.Mute = true;
					_VideoPlayer.Events.PlayerLengthChanged += this.OnVideoPlayerLengthChanged;
					_VideoPlayer.Events.PlayerPositionChanged += this.OnVideoPlayerPositionChanged;
					/*
					_VideoFrameRenderer = _VideoPlayer.CustomRendererEx;
					if (_VideoPixelWidth > 0 && _VideoPixelHeight > 0)
					{
						_VideoFrameRenderer.SetFormatSetupCallback((format) =>
						{
							return new BitmapFormat(_VideoPixelWidth, _VideoPixelHeight, ChromaType.I420);
						});
						_VideoFrameRenderer.SetCallback(this.VideoFrameCallback);
					}
					*/
				}

				//初始化播放器
				if (_MediaState == PlayableMediaState.Stopped)
				{
					_VideoPlayer.Open(_Media);
					_VideoPlayer.WindowHandle = _VideoOutputWindowHandle;
					_VideoPlayer.Volume = (int)(_Volume * 100 + 0.5);
					_VideoPlayer.Mute = (_IsVolumeSync ? _IsMuted : true);
					if (_Duration != null)
						_VideoPlayer.Position = ((float)_Position.GetValueOrDefault() / _Duration.Value);
				}

				//播放
				_VideoPlayer.Play();
				if (_Position > 0 && _Duration > 0)
					_VideoPlayer.Position = (_Position.Value / (float)_Duration.Value);
				this.ChangeMediaState(PlayableMediaState.Playing);
			}

			//配置畫面緩衝區
			/*
			lock (_VideoFrameBufferLock)
			{
				if (_VideoFrameBuffer == IntPtr.Zero && _VideoPixelWidth > 0 && _VideoPixelHeight > 0)
				{
					_VideoFrameBuffer = Marshal.AllocHGlobal(_VideoPixelWidth * _VideoPixelHeight * 4);
				}
			}
			*/
		}
		#endregion
		#region PlayablePositionChanged
		public event EventHandler PlayablePositionChanged
		{
			add
			{
				lock (_EventSyncRoot)
				{
					_PlayablePositionChangedHandlers += value;
				}
			}
			remove
			{
				lock (_EventSyncRoot)
				{
					_PlayablePositionChangedHandlers -= value;
				}
			}
		}
		#endregion
		#region PlayablePositionEnd
		public long? PlayablePositionEnd
		{
			get
			{
				return _PlayablePositionEnd;
			}
		}
		#endregion
		#region PlayablePositionStart
		public long? PlayablePositionStart
		{
			get
			{
				return _PlayablePositionStart;
			}
		}
		#endregion
		#region Position
		public long? Position
		{
			get
			{
				return _Position;
			}
			set
			{
				lock (this)
				{
					//確認狀態
					if (_IsDisposed)
						throw new ObjectDisposedException("VlcVideo");
					if (!_CanSeek)
						throw new InvalidOperationException();
					if (_MediaState == PlayableMediaState.Error)
						return;
					if (_Duration == null)
						return;

					//確認參數
					if (value == null)
						throw new ArgumentException();

					//修正時間
					long position = value.Value;
					if (position < 0)
						position = 0;
					if (position > _Duration)
						position = _Duration.Value;

					//確認位置是否改變
					if (_Position == position)
						return;

					//變更播放位置
					if (_VideoPlayer != null)
					{
						try
						{
							_VideoPlayer.Position = ((float)position / _Duration.Value);
						}
						catch
						{
							return;
						}
					}
					_Position = position;
					this.OnVideoPlayerPositionChanged(position);
				}
			}
		}
		#endregion
		#region PositionChanged
		public event EventHandler<DataEventArgs<long?>> PositionChanged
		{
			add
			{
				lock (_EventSyncRoot)
				{
					_PositionChangedHandlers += value;
				}
			}
			remove
			{
				lock (_EventSyncRoot)
				{
					_PositionChangedHandlers -= value;
				}
			}
		}
		#endregion
		#region PropertyChanged
		public event PropertyChangedEventHandler PropertyChanged;
		#endregion
		#region RawAudioFormat
		public IMediaFormat RawAudioFormat
		{
			get
			{
				return _RawAudioFormat;
			}
		}
		#endregion
		#region RawContainerFormat
		public IMediaFormat RawContainerFormat
		{
			get
			{
				return _RawContainerFormat;
			}
		}
		#endregion
		#region RawVideoFormat
		public IMediaFormat RawVideoFormat
		{
			get 
			{
				return _RawVideoFormat;
			}
		}
		#endregion
		#region Stop
		public void Stop()
		{
			lock (this)
			{
				//確認狀態
				if (_IsDisposed)
					throw new ObjectDisposedException("VlcVideo");
				if (_MediaState == PlayableMediaState.Error || _MediaState == PlayableMediaState.Stopped)
					return;

				//停止
				if (_VideoPlayer != null)
					_VideoPlayer.Stop();
				this.ChangeMediaState(PlayableMediaState.Stopped);
			}
		}
		#endregion
		#region VideoFrameCallback
		/*
		void VideoFrameCallback(PlanarFrame frame)
		{
			lock (_VideoFrameBufferLock)
			{
				//確認狀態
				if (_VideoFrameBuffer == IntPtr.Zero)
					return;

				//複製資料
				iNet.Win32.Kernel32.CopyMemory(_VideoFrameBuffer, frame.Planes[0], frame.Lenghts[0]);
			}
			_VideoFrameReadyHandlers.RaiseEvent(this, EventArgs.Empty);
		}
		*/
		#endregion
		#region VideoFrameReady
		/*
		public event EventHandler VideoFrameReady
		{
			add
			{
				lock (_EventSyncRoot)
				{
					_VideoFrameReadyHandlers += value;
				}
			}
			remove
			{
				lock (_EventSyncRoot)
				{
					_VideoFrameReadyHandlers -= value;
				}
			}
		}
		*/
		#endregion
		#region VideoOutputWindowHandle
		public IntPtr VideoOutputWindowHandle
		{
			get
			{
				return _VideoOutputWindowHandle;
			}
			set
			{
				lock (this)
				{
					if (_IsDisposed)
						throw new ObjectDisposedException("VlcVideo");
					_VideoOutputWindowHandle = value;
					if (_VideoPlayer != null)
						_VideoPlayer.WindowHandle = value;
				}
			}
		}
		#endregion
		#region VideoPixelFormat
		public PixelFormat VideoPixelFormat
		{
			get
			{
				return PixelFormats.Bgra32;
			}
		}
		#endregion
		#region VideoPixelHeight
		public int VideoPixelHeight
		{
			get
			{
				return _VideoPixelHeight;
			}
		}
		#endregion
		#region VideoPixelWidth
		public int VideoPixelWidth
		{
			get
			{
				return _VideoPixelWidth;
			}
		}
		#endregion
		#region Volume
		public double Volume
		{
			get
			{
				lock (this)
				{
					if (_VideoPlayer != null)
						_Volume = (_VideoPlayer.Volume / 100.0);
					return _Volume;
				}
			}
			set
			{
				lock (this)
				{
					if (_IsDisposed)
						throw new ObjectDisposedException("VlcVideo");
					_Volume = Math.Min(Math.Max(0, value), 1);
					if (_VideoPlayer != null)
						_VideoPlayer.Volume = (int)(_Volume * 100.0 + 0.5);
				}
			}
		}
		#endregion
	}
}
